<template>
	<view class="container">
		<view class="bg">
			<view class="ti">请先将手机靠近NFC标签</view>
			<!-- <image class="img" mode="heightFix" src="/assets/nfc1.png"></image> -->
			<view class="err">{{errmsg}}</view>
		</view>
		<view v-if="nfcData">
			<view>芯片技术：{{techs.toString()}}</view>
			<view>标签UID：{{uid}}</view>
			<view>可写入：{{isWrite?'是':'否'}}</view>
			<view>NDEF信息</view>
			<view>
				<view v-for="item in messages" class="wp">
					<view>id：{{item.id}}</view>
					<view>type：{{item.type}}</view>
					<view>payload：{{item.payload}}</view>
				</view>
			</view>
		</view>

		<view v-if="isWrite" class="wr">
			<view class="uni-form-item uni-column">
				<view class="title">写入payload内容：</view>
				<input class="uni-input" v-model="content" placeholder="请填写内容" />
			</view>
			<button @click="writeData">写入</button>
		</view>
	</view>
</template>

<script setup>
	import {
		ref,
		computed
	} from 'vue'
	import {
		onLoad,
		onUnload
	} from "@dcloudio/uni-app"
	import {
		byteToString,
		string2ArrayBuffer,
		arrayBufferToString,
		ab2hex
	} from './nfc.js'

	// nfc 实例
	let nfc
	const nfcData = ref(null)
	const errmsg = ref('')
	const content = ref('')
	//可支持写入
	const isWrite = computed(() => techs.value.includes('NDEF'))
	// nfc uid
	const uid = computed(() => {
		if (!nfcData.value) return null
		const data = new Uint8Array(nfcData.value.id)
		let str = ""
		data.forEach(e => {
			let item = e.toString(16)
			if (item.length == 1) {
				item = '0' + item
			}
			item = item.toUpperCase()
			str += item
		})
		return str
	})
	// nfc message
	const messages = computed(() => {
		const result = []
		if (!nfcData.value) return result
		if (Array.isArray(nfcData.value.messages) && nfcData.value.messages.length > 0) {
			let cordsArray = nfcData.value.messages[0].records;
			cordsArray.find(item => {
				const fn = key => arrayBufferToString(new Uint8Array(item[key]).buffer)
				const id = fn('id');
				const type = fn('type');
				const payload = fn('payload');
				result.push({
					id,
					type,
					payload,
				})
			});
		}
		return result
	})
	// nfc techs
	const techs = computed(() => {
		if (!nfcData.value) return []
		return nfcData.value.techs
	})

	// nfc 错误码
	const NFCERR = {
		13000: '设备不支持NFC',
		13001: '系统NFC开关未打开'
	}

	onLoad(() => {
		nfcData.value = null
		nfc = wx.getNFCAdapter()
		startDiscovery()
	})

	onUnload(() => {
		closeNFC()
	})

	function closeNFC() {
		nfc.offDiscovered();
		nfc.stopDiscovery();
	}

	function startDiscovery() {
		nfc.startDiscovery({
			success() {
				nfc.onDiscovered(res => {
					nfcData.value = res
					errmsg.value = ''
				})
			},
			fail(err) {
				console.error('startDiscovery fail', err)
				errmsg.value = NFCERR[err.errCode] || '请检查NFC功能是否正常!'
			}
		})
	}


	function writeData() {
		errmsg.value = ''
		// 获取NDEF对象
		const NFCTab = nfc.getNdef()
		// 连接标签
		NFCTab.connect({
			success: res => {
				// 准备写入的数据
				const records = [{
					id: string2ArrayBuffer(Math.floor(Math.random() * 10000 + 100).toString()),
					payload: string2ArrayBuffer(content.value),
					type: string2ArrayBuffer(Math.floor(Math.random() * 10000 + 100).toString()),
					tnf: 2
				}];
				// 执行写入
				NFCTab.writeNdefMessage({
					records: records,
					success: res => {
						uni.showToast({
							title: '数据写入成功',
							icon: 'success'
						});
					},
					fail: err => {
						console.error(err);
						errmsg.value = NFCERR[err.errCode] || '请检查NFC功能是否正常!'
						uni.showToast({
							title: '数据写入失败',
							icon: 'none'
						});
					},
					complete: res => {
						NFCTab.close()
					}
				});
			},
			fail: error => {
				errmsg.value = '连接设备失败';
				uni.showToast({
					title: '连接设备失败',
					icon: 'error'
				});
			}
		});
	}
</script>

<style lang="less">
	.container {
		padding: 10rpx;
	}

	.bg {
		width: 100%;
		text-align: center;
		margin: 30rpx 0;

		.err {
			color: #f00a;
		}
	}

	.wp {
		padding: 20rpx;
		border: 1px solid #ccc;
		margin-top: 10rpx;
	}

	.wr {
		position: fixed;
		bottom: 30rpx;
		width: 100%;
	}

	.uni-input {
		padding: 20rpx;
		border: 1px solid #ccc;
	}
</style>